﻿using cma.cimiss;
using cma.cimiss.client;
using iTelluro.Explorer.Infrastructure.CrossCutting.Logging;
using iTelluro.Explorer.Infrastructure.CrossCutting.NetFramework.Logging;
using Surfer;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;

namespace SXMeteorological.Data.Utility
{
    public class Render
    {
        //插值文件
        private string _interpolationDatFilePath;
        //行政区划范围
        private double _xMin;
        private double _xMax;
        private double _yMin;
        private double _yMax;
        private string _featureName;
        private int _width;
        private int _height;
        private double left;
        private double top;
    
        //参数
       private Dictionary<string, string> _paraments = new Dictionary<string, string>();
       string _interfaceName = string.Empty;
       string _outputgrid = string.Empty;
       string _blnPath = string.Empty;
       string _tempDatFilePath = string.Empty;
       string _mapName = string.Empty;
       string _showCityNameDat = string.Empty;
       string _colorLevelPath = string.Empty;
       string _time = string.Empty;
       string _regionName = string.Empty;
       string _datfullpath = string.Empty;
       private readonly ILogger _logger;
       private string _isHourOrDay = string.Empty;
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="xmin">经度</param>
        /// <param name="xmax">经度</param>
        /// <param name="ymin">纬度</param>
        /// <param name="ymax">纬度</param>
        /// <param name="para">接口参数</param>
        /// <param name="interfaceName">接口名</param>
        /// <param name="featureName">要素名称（生成图片放置的位置）</param>
        /// <param name="blnPath">行政区划bln全路径</param>
        /// <param name="mapName">出图的图名</param>
        /// <param name="showcityNameDat">显示各地区的中心点dat</param>
        /// <param name="colorpath">色标文件</param>
        public Render(string regionName,string time,RegionPro pro,Dictionary<string,string> para,string interfaceName,string featureName,string mapName,string colorpath,string hourOrday)
        {
            _logger = LoggerFrameFactory.CreateLog();
            _xMin = pro.XMin;
            _yMin = pro.YMin;
            _xMax = pro.XMax;
            _yMax = pro.YMax;
            _height = pro.Height;
            _width = pro.Width;
            left = pro.left;
            top = pro.top;
            _time = time;
            _regionName = regionName;
            _interfaceName=interfaceName;
            _featureName = featureName;
            _mapName = mapName;
            _paraments = para;
            _blnPath = pro.BlnPath;
            _showCityNameDat = pro.ShowCityNameDatPath;
            _colorLevelPath = colorpath;
            _isHourOrDay = hourOrday;
        }

        //获取要素数据 转成dat文件
        private string  GetDatFileData(string interfaceId)
        {
            string datPath = string.Empty;
            try
            {
                InterfaceUse intF = new InterfaceUse();
                RetArray2D retArray2D = intF.QueryDataByInterface(_interfaceName, _paraments);
                if (retArray2D.data.Length == 0)
                {
                    _logger.LogInfo(_time + ":GetDatFileData查到的数据为0行" + ":" + _mapName);
                    return null;
                }
                string path = AppDomain.CurrentDomain.BaseDirectory;
                //临时目录
                var tempDir = Path.Combine(path, "temp");
                if (!Directory.Exists(tempDir))
                {
                    Directory.CreateDirectory(tempDir);
                }
                var guid = Guid.NewGuid().ToString();
                var currDir = Path.Combine(tempDir, guid);
                Directory.CreateDirectory(currDir);
                _tempDatFilePath = currDir;
                //散列点文件
                using (var dataStreamW = File.CreateText(Path.Combine(currDir, "data.dat")))
                {
                    dataStreamW.WriteLine(string.Format("{0}\t{1}\t{2}", "经度", "纬度", _featureName));
                    if (retArray2D.data.Length != 0)
                    {
                        for (var i = 1; i < retArray2D.data.Length; i++)
                        {
                            string[] s = retArray2D.data[i];
                            if (s[2] != "999999" && s[2] != "999998")
                            {
                                if (s[2] == "999990")
                                    s[2] = "0";
                                dataStreamW.WriteLine(string.Format("{0}\t{1}\t{2}", s[1], s[0], s[2]));
                            }
                        }
                    }
                    dataStreamW.Flush();
                    dataStreamW.Close();
                };
                datPath = Path.Combine(currDir, "data.dat");
                _interpolationDatFilePath = Path.GetDirectoryName(datPath);
              
            }
            catch (Exception ex)
            {
                _logger.LogError(string.Format("GetDatFile{0}数据生成失败#{1}：{2}", _mapName, DateTime.Now, ex.Message));
            }
            return datPath;
        }

        /// <summary>
        /// 插值
        /// </summary>
        private void Interpolation()
        {
            string datfullpath = GetDatFileData(_interfaceName);
            _datfullpath = datfullpath;
            string dpath = @"D:\Rending\" + _time.Remove(8,6) +"000000"+ @"\" + _featureName + @"\" + _regionName + @"\" + DateTime.Now.ToString("yyyyMMddHH") + "0000" + ".png";
           //_logger.LogInfo(":Interpolation" + ":_datfullpath" +_datfullpath + DateTime.Now+_blnPath);
            if (!string.IsNullOrEmpty(datfullpath) && !string.IsNullOrEmpty(dpath))
            {
                Application app = new Application();
                try
                {
                    app.GridData2(DataFile: datfullpath,          //数据文件地址
                         xCol: 1,                                        //x为第一列数据
                         yCol: 2,                                        //y为第二列数据
                         zCol: 3,                                        //z为第三列数据
                         DupMethod: Surfer.SrfDupMethod.srfDupNone,
                          xMin: _xMin,
                          xMax: _xMax,
                          yMin: _yMin,
                          yMax: _yMax,//y最大值
                         Algorithm: Surfer.SrfGridAlgorithm.srfKriging,  //插值算法反距离加权
                          NumCols: 1000,      //x方向插值数据量 x经度
                         NumRows: 1000,
                         OutGrid: _interpolationDatFilePath + @"\grid.grd",                     //返回文件为gridfile
                         OutFmt: Surfer.SrfGridFormat.srfGridFmtAscii);  //返回文件编码为Ascii

                    //边界锯齿
                   // app.GridSplineSmooth(_interpolationDatFilePath + @"\grid.grd", 8, 8, SrfSplineMethod.srfSplineInsert, _interpolationDatFilePath + @"\grid2.grd", SrfGridFormat.srfGridFmtAscii);
                    //边界白化
                    app.GridBlank(_interpolationDatFilePath + @"\grid.grd",
                     _blnPath,
                     Path.Combine(_interpolationDatFilePath, "out.grd"),
                     SrfGridFormat.srfGridFmtAscii);
                    _outputgrid = _interpolationDatFilePath + @"\out.grd";
                    app.Visible = false;

                }
                catch (Exception ex)
                {
                    _logger.LogError(string.Format("Interpolation{0}数据生成失败#{1}：{2}",_mapName, DateTime.Now, ex.Message));
                }
                finally
                {
                    app.Quit();
                    System.GC.Collect(System.GC.GetGeneration(app));
                }
            }
            else
            {
                _logger.LogInfo(_time + ":Interpolation查到的数据为0行" + ":" + _mapName+DateTime.Now);
            }
        }
        /// <summary>
        /// 渲染
        /// </summary>
        public  void RenderMap()
        {
            
                Application app = new Application();
               
                    string path = Path.GetDirectoryName(_blnPath);
                    Interpolation();
                    string dpath = @"D:\Rending\" + _time.Remove(8, 6) + "000000" + @"\" + _featureName + @"\" + _regionName + @"\" + DateTime.Now.ToString("yyyyMMddHH") + "0000" + ".png";
                    if (!string.IsNullOrEmpty(_datfullpath) && !string.IsNullOrEmpty(dpath))
                    {
                        try
                        {
                            app.Visible = false;
                            // app.Caption = @"陕西省自动站雨量等值线图";
                            app.Caption = _mapName;
                            // app.GridBlank(_outputgrid, _blnPath, path + @"\xian.grd", SrfGridFormat.srfGridFmtAscii);
                            Surfer.IDocuments Docs = app.Documents;
                            Surfer.IPlotDocument PlotDoc = (Surfer.IPlotDocument)Docs.Add(SrfDocTypes.srfDocPlot);
                            Surfer.IMapFrame MapF = PlotDoc.Shapes.AddContourMap(_outputgrid);
                          

                            IMapFrame MapF1 = PlotDoc.Shapes.AddBaseMap(_blnPath);  //添加边界底图
                           IBaseMap basemap = (Surfer.IBaseMap)MapF1.Overlays.Item(1);
                           basemap.Line.Width = 0.01;
                            MapF.SetLimits(xMin: _xMin,
                                 xMax: _xMax,
                                 yMin: _yMin,
                                 yMax: _yMax);
                          //  MapF.xMapPerPU = (_xMax - _xMin) /16;
                           // MapF.yMapPerPU = (_yMax - _yMin) /16;

                            //显示等值线上的数值
                            IPostMap PostMap1 = (IPostMap)PlotDoc.Shapes.AddPostMap(_showCityNameDat, 1, 2, 3, 0, 0).Overlays.Item(1);
                            PostMap1.LabelPos = SrfPostPosType.srfPostPosAbove;
                            PostMap1.LabelFont.Face = @"宋体";
                            PostMap1.LabelFont.Size = 9;
                            PostMap1.LabelFont.Bold = false;
                            PostMap1.Symbol.Index = 11;
                            PostMap1.Symbol.Color = srfColor.srfColorBlack70;
                            PostMap1.Symbol.FillColor = srfColor.srfColorBlack70;
                            PostMap1.Symbol.Size = 0.04;
                            //等值线填充
                            Surfer.IContourMap ContourMap = (Surfer.IContourMap)MapF.Overlays.Item(1);

                           
                            ContourMap.Opacity = 80;
                            ContourMap.FillContours = true;//添加颜色填充
                            ContourMap.ShowColorScale = true;//图例显示
                            //ContourMap.ColorScale.Height = 1.6;
                            //ContourMap.ColorScale.Width = 0.6;
                            //ContourMap.ColorScale.Left = ContourMap.Left + 4;
                            //ContourMap.ColorScale.Top = ContourMap.Top - 7.5;
                            ContourMap.ColorScale.LabelFont.Size = 12;
                            ContourMap.ColorScale.LabelFont.Face = @"宋体";
                            ContourMap.ColorScale.LabelFont.Bold = true;
                           // ContourMap.ColorScale.Opacity = 80;     
                            string time2 = DateTime.Now.ToString("yyyyMMddHH") + "0000";
                            string startTime= string.Empty;
                            string endTime = string.Empty;
                            string name = string.Empty;
                            string dt = time2.Substring(0, 4) + "-" + time2.Substring(4, 2) +
"-" + time2.Substring(6, 2) + " " + time2.Substring(8, 2) + ":" + time2.Substring(10, 2) + ":" + time2.Substring(12, 2);
                            switch (_isHourOrDay)
                            {
                                case "h":
                                    startTime = Convert.ToDateTime(dt).AddHours(-1).ToString("yyyy年MM月dd日HH时");
                                    endTime = Convert.ToDateTime(dt).ToString("yyyy年MM月dd日HH时");
                                    name = "      " + _mapName + "\n" + startTime + " - " + endTime;
                                    break;
                                case "d":
                                    startTime = Convert.ToDateTime(dt).AddDays(-1).ToString("yyyy年MM月dd日");
                                    endTime = Convert.ToDateTime(dt).ToString("yyyy年MM月dd日");
                                    name = "      " + _mapName + "\n" + startTime + " - " + endTime;
                                    break;
                                case "y":
                                    startTime = Convert.ToDateTime(dt).ToString("yyyy年");
                                    name = "      " + startTime + _mapName;
                                    break;
                                case "m":
                                    startTime = Convert.ToDateTime(dt).ToString("yyyy年MM月");
                                    endTime = Convert.ToDateTime(dt).ToString("yyyy年MM月");
                                    name = "      " + startTime + _mapName;
                                    break;
                                case "cj":
                                    startTime = Convert.ToDateTime(dt).ToString("yyyy年") + "03月";
                                    endTime = Convert.ToDateTime(dt).ToString("yyyy年") + "05月";
                                    name = "      " + _mapName + "\n" + startTime + " - " + endTime;
                                    break;
                                case "xj":
                                    startTime = Convert.ToDateTime(dt).ToString("yyyy年") + "06月";
                                    endTime = Convert.ToDateTime(dt).ToString("yyyy年") + "08月";
                                    name = "      " + _mapName + "\n" + startTime + " - " + endTime;
                                    break;
                                case "qj":
                                    startTime = Convert.ToDateTime(dt).ToString("yyyy年") + "9月";
                                    endTime = Convert.ToDateTime(dt).ToString("yyyy年") + "11月";
                                    name = "      " + _mapName + "\n" + startTime + " - " + endTime;
                                    break;
                                case "dj":
                                    startTime = Convert.ToDateTime(dt).ToString("yyyy年") + "12月";
                                    endTime = Convert.ToDateTime(dt).ToString("yyyy年") + "2月";
                                    name = "      " + _mapName + "\n" + startTime + " - " + endTime;
                                    break;
                                case "sx":
                                    startTime = Convert.ToDateTime(dt).ToString("yyyy年MM月") + "上旬";
                                    endTime = Convert.ToDateTime(dt).ToString("yyyy年MM月") + "上旬";
                                    name = "      " + startTime + _mapName;
                                    break;
                                case "zx":
                                    startTime = Convert.ToDateTime(dt).ToString("yyyy年MM月") + "中旬";
                                    endTime = Convert.ToDateTime(dt).ToString("yyyy年MM月") + "中旬";
                                    name = "      " + startTime + _mapName;
                                    break;
                                case "xx":
                                    startTime = Convert.ToDateTime(dt).ToString("yyyy年MM月") + "下旬";
                                    endTime = Convert.ToDateTime(dt).ToString("yyyy年MM月") + "下旬";
                                    name = "      " + startTime + _mapName;
                                    break;

                            }
             
                
                         
                         

                            //加载系统颜色
                            // ContourMap.FillForegroundColorMap.LoadFile(@"C:\Program Files\Golden Software\Surfer 12\ColorScales\Rainbow.clr");
                            StreamReader read = new StreamReader(_colorLevelPath);
                            String s1 = String.Empty;
                            int count = 0;
                            ArrayList colorred = new ArrayList();
                            ArrayList colorgreen = new ArrayList();
                            ArrayList colorblue = new ArrayList();
                            ArrayList value = new ArrayList();
                            double min1 = ContourMap.Grid.zMin - 2;
                            double max1 = ContourMap.Grid.zMax+2;
                            List<string> array = new List<string>();
                            while ((s1 = read.ReadLine()) != null)
                            {
                                if (count != 0)
                                {
                                    array.Add(s1.ToString());
                                }
                                count++;
                            }
                            double[] CustomLevels = new double[array.Count];
                            for (int j = 0; j < array.Count; j++)
                            {
                                string yyy = string.Empty;
                                if (array[j].Split('*')[3].ToString().StartsWith("<") || array[j].Split('*')[3].ToString().StartsWith(">"))
                                { yyy = array[j].Split('*')[3].ToString().Substring(1); }
                                else { yyy = array[j].Split('*')[3].ToString(); }
                                CustomLevels[j] = Convert.ToDouble(yyy);
                                if (CustomLevels[j] >= min1 && CustomLevels[j] <= max1)
                                {
                                    colorred.Add(Convert.ToInt32(array[j].Split('*')[0].ToString()));
                                    colorgreen.Add(Convert.ToInt32(array[j].Split('*')[1].ToString()));
                                    colorblue.Add(Convert.ToInt32(array[j].Split('*')[2].ToString()));
                                    value.Add(CustomLevels[j]);
                                }
                            }
                            int[] r = new int[colorred.Count];
                            colorred.CopyTo(r);
                            int[] g = new int[colorgreen.Count];
                            colorgreen.CopyTo(g);
                            int[] b = new int[colorblue.Count];
                            colorblue.CopyTo(b);
                            double[] y = new double[value.Count];
                            value.CopyTo(y);
                            Surfer.ILevels Levels = ContourMap.Levels;
                            Levels.Set(y);
                            for (int level = 0; level < value.Count; level++)
                            {

                                Levels.Item(level + 1).Fill.ForeColorRGBA.Red = r[level];
                                Levels.Item(level + 1).Fill.ForeColorRGBA.Green = g[level];
                                Levels.Item(level + 1).Fill.ForeColorRGBA.Blue = b[level];
                            }

                            ContourMap.SmoothContours = SrfConSmoothType.srfConSmoothHigh;//等值线平滑
                            for (int i = 0; i < ContourMap.Levels.Count; i++)
                            {
                                Levels.Item(i + 1).ShowLabel = true;                 //
                                Levels.Item(i + 1).ShowHach = false;                 //
                              Levels.Item(i + 1).Line.Style = "Solid";         //显示线
                              Levels.Item(i + 1).Line.ForeColor = srfColor.srfColorWhite;
                               
                               Levels.Item(i + 1).Line.Width = 0.01;
                              

                            }
                            //ContourMap.Levels.LoadFile(path + @"\colorlev\" + colorfile);
                            //覆盖所有地图

                            PlotDoc.Shapes.SelectAll();

                            Surfer.IMapFrame MapFrame = PlotDoc.Selection.OverlayMaps();

                            MapFrame.Axes.Item(1).Visible = false;
                            MapFrame.Axes.Item(2).Visible = false;

                            MapFrame.Axes.Item(3).Visible = false;

                            MapFrame.Axes.Item(4).Visible = false;
                            MapFrame.SetLimits(xMin: _xMin,
                                xMax: _xMax,
                                yMin: _yMin,
                                yMax: _yMax);

                            Surfer.IText Text1 = PlotDoc.Shapes.AddText(ContourMap.Left + left, ContourMap.Top + top, name);
                            Text1.Font.Size = 12;
                            Text1.Font.Face = @"宋体";
                            Text1.Font.Bold = true;

                            //PlotDoc.SaveAs(path + @"\Data.srf", "", SrfSaveFormat.srfSaveFormatDat);
                         //   string strWH = string.Format("width = {0:f0}, height = {1:f0}, KeepAspect = 1, ColorDepth = 32", _width*2, _height*2);//设置输出图片的高度和宽度
                            //输出文件
                         //   PlotDoc.Export2(_tempDatFilePath + @"\" + _time + ".png", SelectionOnly: false, Options: strWH, FilterId: "png");//设置输出图片格式名
                            PlotDoc.Export(_tempDatFilePath + @"\" + time2 + ".png", false, "Defaults=1,width=" + _width + ",KeepAspect=1,ColorDepth=32,Automatic=0,Quality=100");

                            string time = time2.Remove(8, 6) + "000000";
                           
                            //发布文件
                            string outputFile = @"D:\Rending\"+time+@"\" + _featureName + @"\" + _regionName;


                            if (!Directory.Exists(outputFile))
                            {
                                Directory.CreateDirectory(outputFile);
                            }
                            File.Copy(Path.Combine(_tempDatFilePath, time2 + ".png"), outputFile + @"\" + time2 + ".png", true);
                            Directory.Delete(_tempDatFilePath, true);

                        }
                        catch (Exception ex)
                        {
                            _logger.LogError(string.Format("RenderMap{0}数据生成失败#{1}：{2}", _mapName, DateTime.Now, ex.Message));
                           
                        }
                        finally
                        {
                            app.Documents.CloseAll(SrfSaveTypes.srfSaveChangesNo);
                            app.Quit();
                            System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
                            System.GC.Collect(System.GC.GetGeneration(app));
                            app = null;
                        }
                    }
                    else
                    {
                        _logger.LogInfo(_time + ":RenderMap查到的数据为0行" + ":" + _mapName + DateTime.Now);
                    }
        }
       
    }
}
